home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 October
/
CHIP Turkiye Ekim 2000.iso
/
prog
/
naps
/
04
/
setup.exe
/
Gnucleus
/
HeaderCtrlEx.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-07-06
|
10KB
|
371 lines
/********************************************************************************
Gnucleus - A node application for the Gnutella network
Copyright (C) 2000 John Marshall
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For support, questions, comments, etc...
E-Mail:
swabby@c0re.net
Address:
21 Cadogan Way
Nashua, NH, USA 03062
********************************************************************************/
#include "stdafx.h"
#include "HeaderCtrlEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "Resource.h"
/////////////////////////////////////////////////////////////////////////////
// CMyHeaderCtrl
CMyHeaderCtrl::CMyHeaderCtrl() : marker_rect(0,0,0,0)
{
m_pWidth = NULL;
m_bDragging = FALSE;
m_bCheckForDrag = FALSE;
m_fpDragCol = NULL;
m_pOwnerWnd = NULL;
// Default to being unsorted.
m_bSortAsc = FALSE;
m_nSortCol = -1;
}
CMyHeaderCtrl::CMyHeaderCtrl(CWnd *pWnd, void (CWnd::*fpDragCol)(int, int))
: marker_rect(0,0,0,0)
{
m_pWidth = NULL;
m_bDragging = FALSE;
m_bCheckForDrag = FALSE;
m_fpDragCol = fpDragCol;
m_pOwnerWnd = pWnd;
}
CMyHeaderCtrl::~CMyHeaderCtrl()
{
}
BEGIN_MESSAGE_MAP(CMyHeaderCtrl, CHeaderCtrl)
//{{AFX_MSG_MAP(CMyHeaderCtrl)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyHeaderCtrl message handlers
void CMyHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if( (MK_LBUTTON & nFlags) == 0)
{
// The left mouse button is not pressed - so reset flags
m_bCheckForDrag = FALSE;
m_bDragging = FALSE;
}
else if( m_bDragging )
{
// Get column number that falls under the mouse
int i=0, cx = 0;
if( point.x > 0 )
for( i = 0; i < GetItemCount(); i++ )
{
if( point.x >= cx && point.x < cx + m_pWidth[i] )
break;
cx += m_pWidth[i];
}
if( i != m_nDropPos )
{
m_nDropPos = i;
CRect rect;
GetWindowRect( &rect );
// Invalidate area occupied by previous marker
InvalidateRect( &marker_rect );
// Draw a new marker
CClientDC dc(this);
POINT pts[3];
pts[0].x = cx; pts[1].x = cx -3; pts[2].x = cx +3;
pts[0].y = rect.Height(); pts[1].y = pts[2].y = rect.Height() -7;
dc.Polygon( pts, 3 );
// save marker information
marker_rect.left = cx - 4;
marker_rect.top = rect.Height() -8;
marker_rect.right = cx + 4;
marker_rect.bottom = rect.Height();
}
return;
}
else if( m_bCheckForDrag )
{
// The mouse button was pressed over a column header
// and now the mouse has moved - so start drag
m_bCheckForDrag = FALSE;
m_bDragging = TRUE;
m_nDropPos = m_nDragCol;
SetCapture();
// Store information for later use
int iCount = GetItemCount();
HD_ITEM hd_item;
m_pWidth = new int[iCount];
for( int i = 0; i < iCount; i++ )
{
hd_item.mask = HDI_WIDTH;
GetItem( i, &hd_item );
m_pWidth[i] = hd_item.cxy;
}
return;
}
CHeaderCtrl::OnMouseMove(nFlags, point);
}
/**
* Finish a column drag if one was started.
*/
void CMyHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
ASSERT( m_pOwnerWnd != NULL && m_fpDragCol != NULL );
if( m_bDragging )
{
m_bDragging = FALSE;
delete[] m_pWidth;
ReleaseCapture();
Invalidate();
// Call the callback function.
if( m_nDragCol != m_nDropPos && m_nDragCol != m_nDropPos -1 )
{
(m_pOwnerWnd->*m_fpDragCol)( m_nDragCol, m_nDropPos );
// If the currently sorted column is the one being dragged
// Mark it as being sorted in its dropped position
if ( m_nSortCol == m_nDragCol )
SetSortImage( m_nDropPos, m_bSortAsc );
}
}
CHeaderCtrl::OnLButtonUp(nFlags, point);
}
/**
* Setup a callback for the dragging of a column
*
*/
void CMyHeaderCtrl::SetCallback( CWnd* pWnd, void (CWnd::*fpDragCol)(int, int) )
{
m_fpDragCol = fpDragCol;
m_pOwnerWnd = pWnd;
}
/**
* See if a drag is starting over one of the columns.
*/
void CMyHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// Determine if mouse was pressed over a column header
HD_HITTESTINFO hd_hittestinfo;
hd_hittestinfo.pt = point;
SendMessage(HDM_HITTEST, 0, (LPARAM)(&hd_hittestinfo));
if( hd_hittestinfo.flags == HHT_ONHEADER )
{
m_nDragCol = hd_hittestinfo.iItem;
m_bCheckForDrag = TRUE;
}
CHeaderCtrl::OnLButtonDown(nFlags, point);
}
/**
* Set the type of image to display in this column.
* (Either ascending, or descending)
*/
int CMyHeaderCtrl::SetSortImage( int nCol, BOOL bAsc )
{
m_nSortCol = nCol;
m_bSortAsc = bAsc;
// Change the item to ownder drawn
HD_ITEM hditem;
hditem.mask = HDI_FORMAT;
GetItem( nCol, &hditem );
hditem.fmt |= HDF_OWNERDRAW;
SetItem( nCol, &hditem );
// Invalidate header control so that it gets redrawn
Invalidate();
return 1;
}
void CMyHeaderCtrl::RemoveSortImage( int iItem )
{
if( iItem != -1 )
{
HD_ITEM hditem;
hditem.mask = HDI_FORMAT;
GetItem( iItem, &hditem );
hditem.mask = HDI_FORMAT;
hditem.fmt &= ~HDF_BITMAP;
SetItem( iItem, &hditem );
}
}
void CMyHeaderCtrl::RemoveAllSortImages()
{
int iCount = GetItemCount();
for( int i = 0; i < iCount; i++ )
RemoveSortImage( i );
}
void CMyHeaderCtrl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CDC dc;
dc.Attach( lpDrawItemStruct->hDC );
// Get the column rect
CRect rcLabel( lpDrawItemStruct->rcItem );
// Save DC
int nSavedDC = dc.SaveDC();
// Set clipping region to limit drawing within column
CRgn rgn;
rgn.CreateRectRgnIndirect( &rcLabel );
dc.SelectObject( &rgn );
rgn.DeleteObject();
#pragma warning( push , 3)
// Draw the background
dc.FillRect(rcLabel, &CBrush(::GetSysColor(COLOR_3DFACE)));
#pragma warning( pop )
// Labels are offset by a certain amount
// This offset is related to the width of a space character
int offset = dc.GetTextExtent(_T(" "), 1 ).cx*2;
// Get the column text and format
TCHAR buf[256];
HD_ITEM hditem;
hditem.mask = HDI_TEXT | HDI_FORMAT;
hditem.pszText = buf;
hditem.cchTextMax = 255;
GetItem( lpDrawItemStruct->itemID, &hditem );
// Determine format for drawing column label
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP
| DT_VCENTER | DT_END_ELLIPSIS ;
if( hditem.fmt & HDF_CENTER)
uFormat |= DT_CENTER;
else if( hditem.fmt & HDF_RIGHT)
uFormat |= DT_RIGHT;
else
uFormat |= DT_LEFT;
// Adjust the rect if the mouse button is pressed on it
if( lpDrawItemStruct->itemState == ODS_SELECTED )
{
rcLabel.left++;
rcLabel.top += 2;
rcLabel.right++;
}
// Adjust the rect further if Sort arrow is to be displayed
if( lpDrawItemStruct->itemID == (UINT)m_nSortCol )
{
rcLabel.right -= 3 * offset;
}
rcLabel.left += offset;
rcLabel.right -= offset;
// Draw column label
if( rcLabel.left < rcLabel.right )
dc.DrawText(buf,-1,rcLabel, uFormat);
// Draw the Sort arrow
if( lpDrawItemStruct->itemID == (UINT)m_nSortCol )
{
CRect rcIcon( lpDrawItemStruct->rcItem );
// Set up pens to use for drawing the triangle
CPen penLight(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
CPen penShadow(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
CPen *pOldPen = dc.SelectObject( &penLight );
if( m_bSortAsc )
{
// Draw triangle pointing upwards
dc.MoveTo( rcIcon.right - 2*offset, offset-1);
dc.LineTo( rcIcon.right - 3*offset/2, rcIcon.bottom - offset );
dc.LineTo( rcIcon.right - 5*offset/2-2, rcIcon.bottom - offset );
dc.MoveTo( rcIcon.right - 5*offset/2-1, rcIcon.bottom - offset-1 );
dc.SelectObject( &penShadow );
dc.LineTo( rcIcon.right - 2*offset, offset-2);
}
else
{
// Draw triangle pointing downwords
dc.MoveTo( rcIcon.right - 3*offset/2, offset-1);
dc.LineTo( rcIcon.right - 2*offset-1, rcIcon.bottom - offset + 1 );
dc.MoveTo( rcIcon.right - 2*offset-1, rcIcon.bottom - offset );
dc.SelectObject( &penShadow );
dc.LineTo( rcIcon.right - 5*offset/2-1, offset -1 );
dc.LineTo( rcIcon.right - 3*offset/2, offset -1);
}
// Restore the pen
dc.SelectObject( pOldPen );
}
// Restore dc
dc.RestoreDC( nSavedDC );
// Detach the dc before returning
dc.Detach();
}